package com.ujiuye.testcache.service.impl;

import com.ujiuye.testcache.entity.NullValueResultDO;
import com.ujiuye.testcache.entity.Order;
import com.ujiuye.testcache.entity.R;
import com.ujiuye.testcache.filter.RedisBloomFilter;
import com.ujiuye.testcache.mapper.OrderMapper;
import com.ujiuye.testcache.service.OrderService;
import com.ujiuye.testcache.template.CacheLoadble;
import com.ujiuye.testcache.template.CacheTemplate;
import com.ujiuye.testcache.util.RedisLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

//@Transactional
@Service
public class OrderServiceImpl implements OrderService{
    @Autowired
    OrderMapper orderMapper;
    @Autowired
    ValueOperations valueOperations;
    @Autowired
    CacheTemplate cacheTemplate;
    @Autowired
    RedisBloomFilter bloomFilter;
    @Autowired
    private RedisLock redisLock;

    @Override
    public Integer insertOrder(Order order) {
        Integer integer = orderMapper.insertOrder(order);
        return integer;
    }


    //v1：演示缓存穿透问题
    /*public  R selectOrderById(Integer id) {
        //查询缓存
        Object redisObj = valueOperations.get(String.valueOf(id));

        //命中缓存
        if(redisObj != null) {
            //正常返回数据
            return new R().setCode(200).setData(redisObj).setMsg("OK");
        }
        Order order = orderMapper.selectOrderById(id);//查询数据库
        if (order != null) {
            valueOperations.set(String.valueOf(id), order);  //加入缓存
            return new R().setCode(200).setData(order).setMsg("OK");
        }
        return new R().setCode(500).setData(new NullValueResultDO()).setMsg("查询无果");
    }*/
    //v2：演示缓存穿透解决方案1： 缓存空对象
    /*public  R selectOrderById(Integer id) {
        //查询缓存
        Object redisObj = valueOperations.get(String.valueOf(id));

        //命中缓存
        if(redisObj != null) {
            //正常返回数据
            return new R().setCode(200).setData(redisObj).setMsg("OK");
        }
        Order order = orderMapper.selectOrderById(id);
        if (order != null) {
            valueOperations.set(String.valueOf(id), order);  //加入缓存
            return new R().setCode(200).setData(order).setMsg("OK");
        }else{
            valueOperations.set(String.valueOf(id),new NullValueResultDO(),10,TimeUnit.MINUTES);//把空对象加入缓存
        }
        return new R().setCode(500).setData(new NullValueResultDO()).setMsg("查询无果");
    }*/
    //v3：演示缓存穿透解决方案2： 使用布隆过滤器，但是存在缓存穿透风险
    public  R selectOrderById(Integer id) {
       if(!bloomFilter.isExist(String.valueOf(id))){
           return new R().setMsg("查询无果").setData(new NullValueResultDO()).setCode(600);
       }
        //查询缓存
        Object redisObj = valueOperations.get(String.valueOf(id));

        //命中缓存
        if(redisObj != null) {
            //正常返回数据
            return new R().setCode(200).setData(redisObj).setMsg("OK");
        }
        Order order = orderMapper.selectOrderById(id);
        if (order != null) {
            valueOperations.set(String.valueOf(id), order);  //加入缓存
            return new R().setCode(200).setData(order).setMsg("OK");
        }
        return new R().setCode(500).setData(new NullValueResultDO()).setMsg("查询无果");
    }

    //v4：演示缓存击穿解决方案：使用分布式锁
    /*public  R selectOrderById(Integer id) {
        if(!bloomFilter.isExist(String.valueOf(id))){
            return new R().setMsg("查询无果").setData(new NullValueResultDO()).setCode(600);
        }
        Object redisObj = valueOperations.get(String.valueOf(id));//查询缓存
        if(redisObj != null) {//命中缓存
            return new R().setCode(200).setData(redisObj).setMsg("OK");//正常返回数据
        }
        try {
                redisLock.lock(String.valueOf(id));//加锁 setnx
                redisObj = valueOperations.get(String.valueOf(id));//再次查询缓存
                if(redisObj != null) {//命中缓存
                    return new R().setCode(200).setData(redisObj).setMsg("OK");//正常返回数据
                }
                Order order = orderMapper.selectOrderById(id); //查数据库
                if (order != null) {
                    valueOperations.set(String.valueOf(id), order);  //加入缓存
                    return new R().setCode(200).setData(order).setMsg("OK");
                }
        }finally {
            redisLock.unlock(String.valueOf(id));//释放锁
        }
        return new R().setCode(500).setData(new NullValueResultDO()).setMsg("查询无果");
    }*/


    //v5：代码优化使用模板方法: 回调方法
    /*public R selectOrderById(Integer id) {
        return cacheTemplate.redisFindCache(String.valueOf(id), 10, TimeUnit.MINUTES, new CacheLoadble<Order>() {
            @Override
            public Order load() {
                return orderMapper.selectOrderById(id);
            }
        },true);
    }*/

    public R synchronizedSelectOrderById(Integer id) {

        return cacheTemplate.findCache(String.valueOf(id), 10, TimeUnit.MINUTES, new CacheLoadble<Order>() {
            @Override
            public Order load() {
                return orderMapper.selectOrderById(id);
            }
        });
    }


    @Override
    public List<Order> selectOrderyAll() {
        return orderMapper.selectOrderyAll();
    }
}
